/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.yonsei.iwb.srf.classifier;

import edu.yonsei.iwb.sdt.refinement.generator.*;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.XSD;
import edu.yonsei.iwb.sdt.algorithm.DCSSearcher;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import edu.yonsei.iwb.sdt.datastructure.tree.BranchingType;
import edu.yonsei.iwb.sdt.datastructure.DecomposeCandidate;
import edu.yonsei.iwb.sdt.datastructure.DecomposeCandidateSet;
import edu.yonsei.iwb.sdt.datastructure.TargetInstance;
import edu.yonsei.iwb.sdt.ontology.PropertyArc;
import edu.yonsei.iwb.sdt.refinement.DLConstructors;
import edu.yonsei.iwb.sdt.refinement.DomainRestrictionRefinement;
import edu.yonsei.iwb.sdt.refinement.ExpandingHistory;
import edu.yonsei.iwb.sdt.refinement.ExpandingHistorySet;
import edu.yonsei.iwb.sdt.refinement.Refinement;
import edu.yonsei.iwb.sdt.refinement.RefinementType;
import edu.yonsei.iwb.sdt.refinement.ValueInfoOfDP;
import edu.yonsei.iwb.sdt.util.SDTLog;
import edu.yonsei.iwb.ts.TSSearch;
import edu.yonsei.iwb.ts.model.ObjectNode;
import edu.yonsei.iwb.ts.model.Triple;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author JDK
 */
public class DomainRestrictionRefinementClassifier {

    private String property;
    private Vector<TargetInstance> instanceSet;
    private int datatype;
    private Object standard;
    private ValueInfoOfDP vio;
    private Vector<PropertyArc> hisPAset;
    private DecomposeCandidateSet dcs;
    private QuantificationRefinementClassifier qrm;

    public Vector<String> satisfiedSet(int datatype, String property, String standard, Vector<String> insset) throws IOException, ParseException {
        Vector<String> resultset = new Vector();
        Hashtable<String, ArrayList<String>> randValueTable = new Hashtable();
        ArrayList<Triple> tripleSet = TSSearch.listTriple(null, property, null);
        for (int i = 0; i < tripleSet.size(); i++) {
            Triple tr = tripleSet.get(i);
            String subject = tr.getSubject();
            ObjectNode on = tr.getObject();
            String value = on.getValue();
            if (randValueTable.containsKey(subject)) {
                ArrayList<String> vset = randValueTable.get(subject);
                if (!vset.contains(value)) {
                    vset.add(value);
                }
            } else {
                ArrayList<String> vset = new ArrayList();
                vset.add(value);
                randValueTable.put(subject, vset);
            }
        }

        Vector<String> css = this.getSatisfiedInstanceSet(standard, datatype, randValueTable);
        for (int i = 0; i < insset.size(); i++) {
            String ins = insset.get(i);
            if (css.contains(ins)) {
                resultset.add(ins);
            }
        }

        return resultset;
    }

    public Vector<Refinement> refinementGenerator(Vector standardset) throws IOException, ParseException {
        //owl:datarange case
        Vector<Refinement> refset = new Vector<Refinement>();

//        ArrayList<String> res = TSSearch.listSubjectResource(property);
//        Vector<TargetInstance> cloneSet = new Vector(instanceSet);
//
//        for (int i = 0; i < standardset.size(); i++) {
//            String st = standardset.get(i).toString();
//            Vector<String> css = this.getSatisfiedInstanceSet(st);
//            Vector<TargetInstance> sfTIset = new Vector();
//            for (int j = 0; j < css.size(); j++) {
//                String result = css.get(j);
//                for (int k = 0; k < this.instanceSet.size(); k++) {
//                    TargetInstance ti = this.instanceSet.get(k);
//                    if (ti.getUri().equals(result)) {
//                        sfTIset.add(ti);
//                        cloneSet.remove(ti);
//                    }
//                }
//            }
//            if (!sfTIset.isEmpty()) {
//                Refinement pref = new DomainRestrictionRefinement(st, "==", property, vio.getType());
//                refset.add(pref);
//            }
//        }
//
//        if (!cloneSet.isEmpty()) {
//            Refinement nref = new DomainRestrictionRefinement(standardset, property);
//            nref.setInstanceSet(cloneSet);
//            nref.setBranchingType(BranchingType.NEGATION_TYPE);
//            refset.add(nref);
//        }

        return refset;
    }

    public Vector<String> satisfiedSet(int datatype, String property, String standard, Vector<String> insset, Vector<PropertyArc> pset, Vector<String> qset) throws IOException, ParseException {
        Vector<String> resultset = new Vector();
        Hashtable<String, ArrayList<String>> randValueTable = new Hashtable();
        ArrayList<Triple> tripleSet = TSSearch.listTriple(null, property, null);
        for (int i = 0; i < tripleSet.size(); i++) {
            Triple tr = tripleSet.get(i);
            String subject = tr.getSubject();
            ObjectNode on = tr.getObject();
            String value = on.getValue();
            if (randValueTable.containsKey(subject)) {
                ArrayList<String> vset = randValueTable.get(subject);
                if (!vset.contains(value)) {
                    vset.add(value);
                }
            } else {
                ArrayList<String> vset = new ArrayList();
                vset.add(value);
                randValueTable.put(subject, vset);
            }
        }
        QuantificationRefinementClassifier qrc = new QuantificationRefinementClassifier();
        Vector<String> hisinsset = this.getSatisfiedInstanceSet(standard, datatype, randValueTable);
        for (int i = pset.size() - 1; i > -1; i--) {
            PropertyArc hisp = pset.get(i);
            Hashtable<String,ArrayList<String>> pastrset = qrc.getPastResAndValueTable(hisp);           
            String quantifier = qset.get(i);
            if (quantifier.equals(DLConstructors.EXISTENTIAL)) {
                hisinsset = qrc.getExistentialResources(hisinsset, hisp, pastrset);
            } else {
                hisinsset = qrc.getUniversalResources(hisinsset, hisp, pastrset);
            }
        }
                        
        for (int i = 0; i < hisinsset.size(); i++) {
            String ins = hisinsset.get(i);
            if(insset.contains(ins)){
                resultset.add(ins);
            }            
        }

        return resultset;        
    }

    public DecomposeCandidateSet refinementGenerator(Vector standardset, Vector<PropertyArc> propertyHistory) throws IOException, ParseException {
        //property set exist and owl:datarange case
//        DecomposeCandidateSet dcs = new DecomposeCandidateSet();
//
//        Hashtable<Integer, ExpandingHistorySet> ehlist = new Hashtable<Integer, ExpandingHistorySet>();
//
//        for (int i = 0; i < standardset.size(); i++) {
//            String st = standardset.get(i).toString();
//            Vector<String> css = this.getSatisfiedInstanceSet(st);
//            ExpandingHistorySet ehs = this.qrm.expandingHistoryCounter(propertyHistory, css);
//            for (int j = 0; j < ehs.size(); j++) {
//                ExpandingHistory eh = ehs.get(j);
//                this.putEH(ehlist, j, eh);
//            }
//        }
//
//        Enumeration<Integer> e = ehlist.keys();
//        while (e.hasMoreElements()) {
//            int key = e.nextElement();
//            ExpandingHistorySet ehs = ehlist.get(key);
//            Vector<Refinement> refset = new Vector<Refinement>();
//            Vector<TargetInstance> cloneSet = new Vector(instanceSet);
//
//            for (int i = 0; i < ehs.size(); i++) {
//                ExpandingHistory eh = ehs.get(i);
////                Refinement pref = new DomainRestrictionRefinement("", standardset.get(i).toString(), "==", eh, property);
//
//                Vector<String> is = eh.getInstanceSet();
//                Vector<TargetInstance> sfTIset = new Vector();
//
//                for (int j = 0; j < is.size(); j++) {
//                    String result = is.get(j);
//                    for (int k = 0; k < this.instanceSet.size(); k++) {
//                        TargetInstance ti = this.instanceSet.get(k);
//                        if (ti.getUri().equals(result)) {
//                            sfTIset.add(ti);
//                            cloneSet.remove(ti);
//                        }
//                    }
//                }
//
//                if (!sfTIset.isEmpty()) {
//                    Refinement pref = new DomainRestrictionRefinement(standardset.get(i).toString(), "==", eh, property, vio.getType());
//                    pref.setInstanceSet(sfTIset);
//                    refset.add(pref);
//                }
//
//
//            }
//            if (!cloneSet.isEmpty()) {
//                Refinement nref = new DomainRestrictionRefinement(standardset, ehs.firstElement(), property);
//                nref.setBranchingType(BranchingType.NEGATION_TYPE);
//                nref.setInstanceSet(cloneSet);
//                refset.add(nref);
//            }
//
//            if (!refset.isEmpty()) {
//                DecomposeCandidate dc = new DecomposeCandidate(refset, RefinementType.DOMAINRESTRICTION);
//                dcs.add(dc);
//            }
////            dcs.printDecomposeCandidateSet();
//        }
        return dcs;
    }

    private void putEH(Hashtable<Integer, ExpandingHistorySet> ehlist, int key, ExpandingHistory eh) {
        if (ehlist.keySet().contains(key)) {
            ehlist.get(key).add(eh);
        } else {
            ExpandingHistorySet ehs = new ExpandingHistorySet();
            ehs.add(eh);
            ehlist.put(key, ehs);
        }
    }

    private Vector<String> getSatisfiedInstanceSet(String standard, int datatype, Hashtable<String, ArrayList<String>> randvt) throws IOException, ParseException {
        Vector<String> css = new Vector();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

//        Hashtable<String, ArrayList<String>> randvt = this.vio.getRandValueTable();        
        Enumeration<String> resources = randvt.keys();
        while (resources.hasMoreElements()) {
            String subject = resources.nextElement();
            ArrayList<String> valueset = randvt.get(subject);

            if (datatype == ValueInfoOfDP.BOOLEAN || datatype == ValueInfoOfDP.STRING) {
                for (int j = 0; j < valueset.size(); j++) {
                    String value = valueset.get(j);
                    if (value.equals(standard)) {
                        css.add(subject);
                        break;
                    }
                }
            } else if (datatype == ValueInfoOfDP.INT) {
                int stan = Integer.parseInt(standard);
                for (int j = 0; j < valueset.size(); j++) {
                    String value = valueset.get(j);
                    int intv = Integer.parseInt(value);
                    if (intv > stan) {
                        css.add(subject);
                        break;
                    }
                }
            } else if (datatype == ValueInfoOfDP.DATARANGE) {
                for (int j = 0; j < valueset.size(); j++) {
                    String value = valueset.get(j);
                    if (value.equals(standard)) {
                        css.add(subject);
                        break;
                    }
                }
            } else if (datatype == ValueInfoOfDP.DATE) {
                Date sDate = formatter.parse(standard);
                for (int j = 0; j < valueset.size(); j++) {
                    String value = valueset.get(j);
                    Date vDate = formatter.parse(value);
                    if (vDate.after(sDate)) {
                        System.out.println(vDate + " > " + sDate);
                        css.add(subject);
                        break;
                    }
                }
            }
        }
        return css;
    }
}
